package cn.iocoder.yudao.module.infra.filter;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * IP地址过滤器，用于从请求头中解析IP地址
 */
@Component
public class IpAddressFilter extends OncePerRequestFilter {

    public static final String X_FORWARDED_FOR = "X-Forwarded-For";
    public static final String PROXY_CLIENT_IP = "Proxy-Client-IP";
    public static final String WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP";
    public static final String HTTP_CLIENT_IP = "HTTP_CLIENT_IP";
    public static final String HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR";
    public static final String X_REAL_IP = "X-Real-IP";
    public static final String UNKNOWN = "unknown";
    public static final String LOCALHOST_IP = "127.0.0.1";
    public static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
    public static final String COMMA = ",";

    public static final String REQUEST_ATTRIBUTE_IP = "requestIp";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String ip = getIpAddress(request);
        request.setAttribute(REQUEST_ATTRIBUTE_IP, ip);
        filterChain.doFilter(request, response);
    }

    /**
     * 获取请求IP地址
     *
     * @param request 请求
     * @return IP地址
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader(X_FORWARDED_FOR);
        if (isUnknown(ip)) {
            ip = request.getHeader(PROXY_CLIENT_IP);
        }
        if (isUnknown(ip)) {
            ip = request.getHeader(WL_PROXY_CLIENT_IP);
        }
        if (isUnknown(ip)) {
            ip = request.getHeader(HTTP_CLIENT_IP);
        }
        if (isUnknown(ip)) {
            ip = request.getHeader(HTTP_X_FORWARDED_FOR);
        }
        if (isUnknown(ip)) {
            ip = request.getHeader(X_REAL_IP);
        }
        if (isUnknown(ip)) {
            ip = request.getRemoteAddr();
            if (LOCALHOST_IP.equals(ip) || LOCALHOST_IPV6.equals(ip)) {
                // 根据网卡取本机配置的IP
                ip = LOCALHOST_IP;
            }
        }

        // 对于通过多个代理的情况，第一个IP为客户端真实IP，多个IP按照','分割
        if (ip != null && ip.contains(COMMA)) {
            ip = ip.substring(0, ip.indexOf(COMMA)).trim();
        }

        return ip;
    }

    /**
     * 检查IP是否未知
     *
     * @param ip IP地址
     * @return 是否未知
     */
    private static boolean isUnknown(String ip) {
        return ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip);
    }
}

